﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Threading;

namespace AllenalaMente.Games.Blocks
{
    public partial class Blocks : UserControl, GameInterface
    {
        private Random random;

        private int score;
        private int giuste, sbagliate;

        private int blocksNum = 5;
        private int solution = 0;
        private List<int> numbers = new List<int>();
        private DispatcherTimer startTimer;
        private TimeSpan startTime;

        // UI
        private UITimer UIgameTimer;
        private UIScore UIgameScore;

        public Blocks()
        {
            InitializeComponent();

            // Initalize game
            random = new Random();
            score = 0;

            // Start timer
            startTimer = new DispatcherTimer();
            startTimer.Interval = TimeSpan.FromMilliseconds(600);
            startTimer.Tick += new EventHandler(startTimer_Tick);
            startTimer.Start();
            startTime = TimeSpan.FromSeconds(3);
            TextBlockReady.Text = Locale.Strings.Ready;

            // UI Game timer
            UIgameTimer = new UITimer(90);
            LayoutRoot.Children.Add(UIgameTimer);
            UIgameTimer.timeOut += new EventHandler(game_TimeOut);
            //UIgameTimer.Start();

            // UI Game Score
            UIgameScore = new UIScore();
            LayoutRoot.Children.Add(UIgameScore);
            Canvas.SetLeft(UIgameScore, 750);

            //CreateCombination();
        }

        public void Clear()
        {
            UIgameTimer.Stop();
            numbers.Clear();
            canvasBlocks.Children.Clear();
        }

        #region Metodi

        private void CreateCombination()
        {
            numbers.Clear();
            canvasBlocks.Children.Clear();

            int offset = (8 - blocksNum) * 50;

            for (int i = 0; i < blocksNum; i++)
            {
                int n = random.Next(1, 15);

                while(numbers.Contains(n))
                    n = random.Next(1, 15);

                numbers.Add(n);

                Block b = new Block(n, (BlockColor)random.Next(0, (int)BlockColor.TotalColors));
                Canvas.SetLeft(b, offset);
                canvasBlocks.Children.Add(b);
                
                offset += 100;

                b.MouseLeftButtonDown += new MouseButtonEventHandler(block_MouseLeftButtonDown);
            }

            solution = 0;

            for (int i = 0; i < blocksNum - 3; i++)
            {
                int index = random.Next(1, numbers.Count());

                solution += numbers[index];
                numbers.RemoveAt(index);
            }

            textBlocksolution.Text = solution.ToString();
        }

        private void CheckSolution()
        {
            int sol = 0;

            for (int i = 0; i < canvasBlocks.Children.Count(); i++)
            {
                Block b = (Block)canvasBlocks.Children[i];
                sol += b.value;
            }

            if (sol < solution)
            {
                imgSbagliato.Opacity = 1;
                Animation.FadeOut(imgSbagliato, 1000);

                CreateCombination();
                sbagliate++;
            }

            if (sol == solution) 
            {
                imgGiusto.Opacity = 1;
                Animation.FadeOut(imgGiusto, 1000);

                CreateCombination();

                // Punti: 100 + (diff. lev * 10)
                int points = 100 + (blocksNum - 4) * 10;

                IncreaseScore(points);
                textBlockPoints.Text = "+" + points;
                hide(textBlockPoints);

                giuste++;

                if (giuste % 3 == 0) blocksNum++;
                if (blocksNum > 7) blocksNum = 7;
            } 
        }

        private bool hasSolution()
        {
            bool hasSol = true;      

            return hasSol;
        }

        private void IncreaseScore(int amount)
        {
            score += amount;
            UIgameScore.SetScore(score);
        }

        #endregion

        #region Animations

        public void Show(UIElement element)
        {
            DoubleAnimation doubleAnimation = new DoubleAnimation();
            doubleAnimation.From = 0;
            doubleAnimation.To = 1;
            doubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(0.5));

            Storyboard.SetTargetProperty(doubleAnimation, new PropertyPath("Opacity"));
            Storyboard.SetTarget(doubleAnimation, element);

            Storyboard sb = new Storyboard();
            sb.Children.Add(doubleAnimation);
            sb.Begin();
        }

        public void hide(UIElement element)
        {
            DoubleAnimation doubleAnimation = new DoubleAnimation();
            doubleAnimation.From = 1;
            doubleAnimation.To = 0;
            doubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(1.0));

            Storyboard.SetTargetProperty(doubleAnimation, new PropertyPath("Opacity"));
            Storyboard.SetTarget(doubleAnimation, element);

            Storyboard sb = new Storyboard();
            sb.Children.Add(doubleAnimation);
            sb.Begin();
        }

        #endregion

        #region Eventi

        private void startTimer_Tick(object sender, EventArgs e)
        {
            startTime = startTime.Subtract(TimeSpan.FromSeconds(1));
            if (startTime.Seconds < 2)
                TextBlockReady.Text = Locale.Strings.GO;
            if (startTime.Seconds < 1)
            {
                // The countdown is finished, the game can start
                startTimer.Tick -= startTimer_Tick;
                CanvasCountdown.Visibility = Visibility.Collapsed;
                UIgameTimer.Start();

                CreateCombination();
            }
        }

        public event GameEvent GameEnd;

        void block_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            Block b = (Block)sender;
            b.hide.Begin();
            b.value = 0;
            b.MouseLeftButtonDown -= block_MouseLeftButtonDown;

            CheckSolution();
        }

        private void game_TimeOut(object sender, EventArgs e)
        {
            // Finito il tempo
            
            GameEventArgs gea = new GameEventArgs();
            gea.reason = GameCloseReason.Timeout;
            gea.score = this.score;
            gea.giuste = giuste;
            gea.sbagliate = sbagliate;

            if (GameEnd != null)
                GameEnd(this, gea);
        }

        #endregion        
    }
}
